package zdar.processing;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.xml.sax.helpers.DefaultHandler;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.XmlReader;
import com.badlogic.gdx.utils.XmlReader.Element;

import zdar.entities.MeleeAction;
import zdar.entities.RangeAction;
import zdar.entities.UnitTemplate;
import zdar.processing.XmlHandler;

/**
 * Class which reads the XML file containing all playable unit types
 * Eventually will need some abstraction to read other XML files, but we'll worry about that when we need them.
 * To use this class, first create a new XmlReader object.
 * Then decide whether you want the ArrayList {getUnitList()} or HashMap {getUnitMap()}
 * @author danbye50
 *
 */

public class XmlHandler extends DefaultHandler{
	
	private ArrayList<UnitTemplate> unitList = new ArrayList<UnitTemplate>();
	private HashMap<String, UnitTemplate> unitMap = new HashMap<String, UnitTemplate>();
	
	public XmlHandler(){
		readUnitXml();
	}
	
	public ArrayList<UnitTemplate> getUnitList(){		
		return unitList;
	}
	public HashMap<String, UnitTemplate> getUnitMap(){
		return unitMap;
	}
	
	private void readUnitXml(){
		XmlReader reader = new XmlReader();
		FileHandle file = Gdx.files.internal("data/units.xml");
		Element root;
		try {
			root = reader.parse(file);
			Iterator it_unit = root.getChildrenByName("unit").iterator();
			
			while (it_unit.hasNext()){
				Element el_unit = (Element) it_unit.next();
				
				//System.out.println(el_unit.get("type"));
				
				// TODO the commented out chunk below
				// If this is correct then get the unit's children
				//Iterator it_unit_properties = el_unit.getchil
				// Send string to another method which determines what it's for
				// that then sends a call to another method which adjusts the UnitTemplate's info
				
				//the above suggestion probably faster, but for now we will keep it simple with this
				UnitTemplate unitTemplate = new UnitTemplate();
				unitTemplate.setDisplayName(el_unit.getChildByNameRecursive("display_name").getText());
				unitTemplate.setWildcard(el_unit.getChildByNameRecursive("wildcard").getText());
				unitTemplate.setDescription(el_unit.getChildByNameRecursive("description").getText());
				
				// Get Attributes
				Iterator it = el_unit.getChildrenByName("attribute").iterator();
				while (it.hasNext()){
					Element el = (Element) it.next();
					//System.out.println(el_att.get("type") + el_att.get("dice"));
					
					switch (el.get("type")){
						case "agility": 	unitTemplate.setAgility(Integer.parseInt(el.get("dice")));	break;
						case "smarts": 		unitTemplate.setSmarts(Integer.parseInt(el.get("dice")));	break;
						case "spirit": 		unitTemplate.setSpirit(Integer.parseInt(el.get("dice")));	break;
						case "strength": 	unitTemplate.setStrength(Integer.parseInt(el.get("dice")));	break;
						case "vigor": 		unitTemplate.setVigor(Integer.parseInt(el.get("dice")));	break;
					}
				}
				
				// Get Skills
				it = el_unit.getChildrenByName("skill").iterator();
				while (it.hasNext()){
					Element el = (Element) it.next();
//					unitTemplate.skills.put(el.get("type"), Integer.parseInt(el.get("dice")));
					unitTemplate.addSkill(el.get("type"), Integer.parseInt(el.get("dice")));
				}
				
				// Get Derived Attributes (which aren't really derived at all in this case)
				it = el_unit.getChildrenByName("derived").iterator();
				while (it.hasNext()){
					Element el = (Element) it.next();
					switch (el.get("type")){
						case "pace": 		unitTemplate.setPace(Integer.parseInt(el.get("value")));		break;
						case "parry": 		unitTemplate.setParry(Integer.parseInt(el.get("value")));		break;
						case "toughness": 	unitTemplate.setToughness(Integer.parseInt(el.get("value")));	break;
					}
				}
				
				// Get Attacks (if any)
				Element attacks = el_unit.getChildByName("attacks");
				if (attacks.getChildCount() > 0){
					it = attacks.getChildrenByName("attack").iterator();
					while(it.hasNext()){
						Element el_attack = (Element) it.next();
						
						// Get Melee Attacks
						// TODO Probably should just merge MeleeAction and RangeAction into Action2 with a flag... we'll see
						if (el_attack.get("type").equalsIgnoreCase("melee")){
							MeleeAction meleeAction = new MeleeAction();
							Iterator it_trait = el_attack.getChildrenByName("trait").iterator();						
							while(it_trait.hasNext()){
								Element el = (Element) it_trait.next();								
								switch (el.get("type")){
									case "name": 		meleeAction.setName(el.get("value"));							break;
									case "attribute_dmg": 	meleeAction.setAttribute_dmg_value(unitTemplate.getAttribute(el.get("value")));	break;
									case "attribute_hit": 	meleeAction.setAttribute_hit_value(unitTemplate.getAttribute(el.get("value")));	break;
									case "dice": 		meleeAction.setDiceType(Integer.parseInt(el.get("value")));			break;
									case "dicecount": 	meleeAction.setDicecount(Integer.parseInt(el.get("value")));	break;
									case "dicemod": 	meleeAction.setDicemod(Integer.parseInt(el.get("value")));		break;
									case "reach": 		meleeAction.setRange1(Integer.parseInt(el.get("value")));		break;
									case "parry": 		meleeAction.setParryMod(Integer.parseInt(el.get("value")));		break;
									case "powerpoints": meleeAction.setPowerPoints(Integer.parseInt(el.get("value")));	break;

								}								
							}// end "trait" loop
							//unitTemplate.meleeAttacks.add(meleeAction);
//							unitTemplate.actions.add(meleeAction);
							unitTemplate.addAction(meleeAction);
							
						// Get Range Attacks
						}else if (el_attack.get("type").equalsIgnoreCase("ranged")){
							RangeAction rangeAction = new RangeAction();
							Iterator it_trait = el_attack.getChildrenByName("trait").iterator();						
							while(it_trait.hasNext()){
								Element el = (Element) it_trait.next();								
								switch (el.get("type")){
									case "name": 		rangeAction.setName(el.get("value"));							break;
									case "attribute_dmg": 	rangeAction.setAttribute_dmg_value(unitTemplate.getAttribute(el.get("value")));	break;
									case "attribute_hit": 	rangeAction.setAttribute_hit_value(unitTemplate.getAttribute(el.get("value")));	break;
									case "dice": 		rangeAction.setDiceType(Integer.parseInt(el.get("value")));			break;
									case "dicecount": 	rangeAction.setDicecount(Integer.parseInt(el.get("value")));	break;
									case "dicemod": 	rangeAction.setDicemod(Integer.parseInt(el.get("value")));		break;
									case "range1": 		rangeAction.setRange1(Integer.parseInt(el.get("value")));		break;
									case "range2": 		rangeAction.setRange2(Integer.parseInt(el.get("value")));		break;
									case "range3": 		rangeAction.setRange3(Integer.parseInt(el.get("value")));		break;
									case "powerpoints": rangeAction.setPowerPoints(Integer.parseInt(el.get("value")));	break;

								}								
							}// end "trait" loop
							//unitTemplate.rangeAttacks.add(rangeAction);
//							unitTemplate.actions.add(rangeAction);
							unitTemplate.addAction(rangeAction);
						}// end melee vs ranged check		
					}// end "attack" loop
				}// end attack count
				
				
				unitTemplate.printInfo();
				/*if (el_unit.getChildByName("frodobaggins") == null){
					System.out.println("where are you mister frodo!?");
				}*/
				
				unitList.add(unitTemplate);

			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}		
		
	}
}
